varying vec3 lightVec, lightVecTan;
varying vec3 halfVec, halfVecTan;
varying vec2 texCoord;
varying vec3 normal;
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform sampler2DShadow shadowMap;
varying vec3 shadowCoord;
uniform int texOn, bumpOn, shadowOn;

const float epsilon = 5e-4;
const float shadowTransp = 0.0;

vec4 ambientColor()
{
	return gl_LightSource[0].ambient * gl_FrontMaterial.ambient +
		gl_LightModel.ambient * gl_FrontMaterial.ambient;
}

vec4 specularColor(float NdotHV)
{
	return gl_FrontMaterial.specular *
			gl_LightSource[0].specular *
			pow(NdotHV, gl_FrontMaterial.shininess);
}

vec4 addTextureColor(vec4 color)
{
	vec4 texel = texture2D(colorMap, texCoord);
	return vec4(texel.xyz * color.xyz, texel.a * color.a);
}

float lookUp(float x, float y)
{
	return clamp( shadow2D(shadowMap, shadowCoord + vec3(x, y, 0)*epsilon).x + shadowTransp, 0.0, 1.0 );
}

vec4 addShadowColor(vec4 color)
{
	float shadow = 0.0;
	float x, y;
	int num = 0;
	
	for (y = -3.5 ; y <=3.5 ; y+=1.0)
	{
		for (x = -3.5 ; x <=3.5 ; x+=1.0)
		{
			shadow += lookUp(x,y);
			num++;
		}
	}
	
	shadow /= float(num) ;
	
	return vec4(shadow * color.rgb, color.a);
}

void main()
{
	float NdotHV = 0.0, NdotL = 0.0;
	vec4 color = ambientColor();
	vec4 diffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse;
	vec3 bump = normalize(normal);
	vec3 light = lightVec;
	vec3 halfV = halfVec;
	
	if( 1 == bumpOn )
	{
		bump = normalize( texture2D(normalMap, texCoord).xyz * 2.0 - 1.0);
		light = lightVecTan;
		halfV = halfVecTan;
	}
	
	NdotL = max(dot(bump,normalize(light)),0.0);
	diffuse *= NdotL;
	if (NdotL > 0.0)
	{
		NdotHV = max(dot(bump,normalize(halfV)),0.0);
				
		if( 1 == shadowOn )
		{
			if( lookUp(0.0, 0.0) > 0.5)
				color += specularColor(NdotHV);
		}
		else
		{
			color += specularColor(NdotHV);
		}
	}
	
	if( 1 == shadowOn )
	{
		diffuse = addShadowColor(diffuse);
	}
	
	color += diffuse;
	
	if( 1 == texOn )
	{
		color = addTextureColor(color);
	}
	
	gl_FragColor = color;
}